<template>
  <div class="networkTest_container">
    <el-card>
      <template #header>
        <div class="flex items-center">
          <el-icon class="m-r-10px"><Connection /></el-icon>
          <span>{{t('networkConfig.ping_test_label')}}</span>
        </div>
      </template>
      <div class="w-100%">
        <el-form 
        ref="pingFormRef" 
        :model="pingFormData" 
        :rules="pingFormRules" 
        inline
        class="w-100% tech-form"
        hide-required-asterisk
        >
          <el-form-item class="tech-form-item" v-for="(item,key) in pingFormItems" :key="key" :label="item.label" :prop="item.prop">
            <component 
            :is="item.component" 
            :style="{width: '200px'}" 
             v-model="pingFormData[key]" 
            :placeholder="item.placeholder" 
            />
          </el-form-item>
        </el-form>
        <div class="flex items-center gap-10px">
            <div 
            :class="{'tech-btn':true,disabled:pingDoneStatus}"
            @click="startPing"  
            color="#1b3a63" 
            :icon="CaretRight"
            >
              <el-icon><CaretRight /></el-icon>
              {{ pingDoneStatus ? "开始ping中..." : t('networkConfig.start_ping_label') }}
            </div>
            <div class="tech-btn" v-show="stopButtonVisible" @click="stopPing"  color="#1b3a63" :icon="CircleClose">
              <el-icon><CircleClose /></el-icon>
              {{ t('networkConfig.stop_ping_label') }}
            </div>
            <div class="tech-btn" @click="clearPinLog" color="#1b3a63" :icon="Delete">
              <el-icon><Delete /></el-icon>
              {{ t('networkConfig.clear_log_label') }}
            </div>
        </div>
        <div class="log_container tech-log" ref="pingLogContainerRef" @scroll="pinScroll">
        <div v-for="(item,index) in pingFormData.pingResult" :key="item">
          <div class="log-item">
            <span class="log-index">[{{index+1}}]</span>
            <span class="log-content">{{item}}</span>
          </div>
          </div>
        </div>
      </div> 
    </el-card>
    <IperfTest />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { 
  Connection,
  VideoPlay,
  VideoPause,
  Delete,
  CaretRight,
  CircleClose
} from '@element-plus/icons-vue'
export default defineComponent({
  name: 'networkTest',
})
</script>

<script setup  lang="ts">
import {ElNotificationFn } from '@/utils/computedUtils'
import {getWebSocketInstance} from '@/utils/websocketExample'
import { useI18n } from 'vue-i18n'
import IperfTest from './components/iperfTest.vue'
const { t } = useI18n()
const wsClient = getWebSocketInstance()
const validateForm = async (formRef: any) => {
  if (!formRef.value) return false
  try {
    await formRef.value.validate()
    return true
  } catch (error) {
    return false
  }
}
const createFormRule = (messageKey: string) => [{
  required: true,
  message: t(messageKey)
}]
const pingFormData = ref<any>({
  ipAddress: '127.0.0.1',
  timeout: 10,
  len:0,
  loading: false,
  pingResult: [],
  isStopPing: false,
  stopLoading:false,
  isManualScroll:false
})
const pingFormItems = computed(() =>{
   return {
    ipAddress:{
      label:t('networkConfig.ipAddress_label'),
      prop:'ipAddress',
      component:'el-input',
      placeholder:t('networkConfig.ipAddress_label')
    },
    timeout:{
      label:t('networkConfig.ping_duration_label'),
      prop:'timeout',
      component:'el-input',
      placeholder:t('networkConfig.ping_duration_label')
    },
    len:{
      label:t('networkConfig.ping_count_label'),
      prop:'len',
      component:'el-input',
      placeholder:t('networkConfig.ping_count_label')

    }
   }
})
const pingFormRef = ref()
const pingLogContainerRef = ref()
const pingFormRules = computed(() => ({
  ipAddress: createFormRule('networkConfig.ipAddress_label'),
  timeout: createFormRule('networkConfig.ping_duration_label'),
  len: createFormRule('networkConfig.ping_count_label')
}))
function scrollToBottom (ref:any) {
  if (ref.value) {
    nextTick(() => {
      ref.value.scrollTo({
        top: ref.value.scrollHeight,
        behavior:'smooth'
      })
    })
  }
}
async function startPing(){
  const res = await validateForm(pingFormRef)
  if(!res){
    ElNotificationFn('warning',t('networkConfig.info_not_complete_label'))
    return
  }
  pingDoneStatus.value = true
  wsClient.send({command:'ping-start',data:{
    addr:pingFormData.value.ipAddress,
    timeout:Number(pingFormData.value.timeout),
    len:Number(pingFormData.value.len)
  }})
}
function stopPing(){
  pingDoneStatus.value = false
  wsClient.send({command:'ping-stop',data:{
    addr:pingFormData.value.ipAddress
  }})
}
function clearPinLog(){
  pingFormData.value.pingResult = []
}
function handlePingStartResponse(data: any) {
  pingFormData.value.pingResult.push(data.msg);
  // 如果用户没有手动滚动或者已经在底部，则自动滚动到底部
  if (!pingFormData.value.isManualScroll) {
    scrollToBottom(pingLogContainerRef);
  }
}
function handlePingStopResponse(data:any){
  pingFormData.value.stopLoading = false
  pingFormData.value.isStopPing = false
  ElNotificationFn('success',t('networkConfig.stop_ping_success_label'))
}
function pinScroll(event: any) {
  const target = event.target;
  // 检查是否接近底部（距离底部20px以内）
  const isNearBottom = target.scrollHeight - target.scrollTop - target.clientHeight < 20;
  // 只有当不在底部时才设置为手动滚动
  pingFormData.value.isManualScroll = !isNearBottom;
}
const pingDoneStatus = ref(false)
const stopButtonVisible = computed(()=>{
  return pingDoneStatus.value
})
function handlePingDoneResponse(){
  pingDoneStatus.value = false
  ElNotificationFn('success',t('networkConfig.ping_done_label'))
}
const wsResponseHandlers:any = {
  'ping':handlePingStartResponse,
  'ping-stop':handlePingStopResponse,
  'ping-done':handlePingDoneResponse
}  
function onWebSocketMessage(response:any){
  const {cmd,data} = response
  if(!Object.keys(wsResponseHandlers).includes(cmd)) return
  wsResponseHandlers[cmd](data)
}
wsClient.on('message',onWebSocketMessage)
</script>

<style lang="scss" scoped>
@import '@/styles/pageLabel.scss';
@import '@/styles/input.scss';
@import '@/styles/form.scss';
@import '@/styles/log_container.scss';
@import '@/styles/card.scss';
.networkTest_container {
  padding: 20px;
}
.m-t-20 {
  margin-top: 20px;
}
.m-r-10px {
  margin-right: 10px;
}
:deep(.el-icon) {
  font-size: 18px;
}
.el-button {
  .el-icon {
    margin-right: 4px;
  }
}
.disabled{
  opacity: 0.7;
  cursor: not-allowed;
  pointer-events: none;
}
.tech-form{
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 15px;
  margin-bottom: 20px;
}
.tech-form-item {
  position: relative;
  margin-bottom: 0 !important;
  
  :deep(.el-form-item__label) {
    font-size: 14px;
    color: #00b4ff;
    text-shadow: 0 0 5px rgba(0, 100, 255, 0.3);
    position: relative;
    padding-left: 12px;
    margin-bottom: 5px;
    
    &:before {
      content: '';
      position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(-50%);
      width: 4px;
      height: 14px;
      background: linear-gradient(to bottom, #00b4ff, transparent);
      border-radius: 2px;
    }
  }
  
  :deep(.el-input__wrapper) {
    background-color: rgba(0, 30, 60, 0.2);
    border: 1px solid rgba(0, 180, 255, 0.3);
    box-shadow: 0 0 5px rgba(0, 120, 215, 0.2);
    transition: all 0.3s;
    
    &:hover, &.is-focus {
      border-color: rgba(0, 180, 255, 0.8);
      box-shadow: 0 0 8px rgba(0, 180, 255, 0.4);
    }
    
    .el-input__inner {
      color: #e0f0ff;
    }
  }
  
  :deep(.el-select) {
    width: 100%;
  }
}

.tech-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 15px;
  background: linear-gradient(to right, #004080, #0070c0);
  border-radius: 4px;
  color: #ffffff;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 0 10px rgba(0, 120, 215, 0.3);
  position: relative;
  overflow: hidden;
  
  &:before {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
    transition: 0.5s;
  }
  
  &:hover:before {
    left: 100%;
  }
  
  &:hover {
    box-shadow: 0 0 15px rgba(0, 180, 255, 0.5);
    transform: translateY(-2px);
  }
  
  .el-icon {
    margin-right: 5px;
  }
}
.tech-log {
  border: 1px solid rgba(0, 150, 220, 0.3);
  border-radius: 4px;
  background-color: rgba(0, 20, 40, 0.3);
  box-shadow: inset 0 0 10px rgba(0, 30, 60, 0.5);
  
  .log-item {
    border-bottom: 1px solid rgba(0, 100, 180, 0.15);
    padding: 8px 12px;
    
    &:hover {
      background-color: rgba(0, 60, 120, 0.15);
    }
    
    .log-index {
      color: #00b4ff;
      margin-right: 10px;
      font-family: 'Consolas', monospace;
    }
    
    .log-content {
      color: #e0f0ff;
      font-family: 'Consolas', monospace;
    }
  }
}
</style>

